package com.joinway.framework.core.plugin;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.joinway.framework.bean.exception.ValidationException;

public class PluginManager {
	private final static Logger log = LoggerFactory.getLogger(PluginManager.class);
	
	@Autowired(required=false) private List<? extends Plugin> plugins;
	
	private static final ConcurrentHashMap<List<? extends Plugin>, Object> pluginCache = new ConcurrentHashMap<>();
//	private static final Map<String, Class<?>> categories = new HashMap<>();
	
//	static {
//		categories.put(Plugin.Category.TableService, value)
//	}
	
	public static<P extends Plugin> P getInstance(List<P> plugins, P defaultValue){
		P plugin = getInstance(plugins);
		
		return plugin != null ? plugin : defaultValue;
	}
	
	@SuppressWarnings("unchecked")
	public static<P extends Plugin> P getInstance(List<P> plugins){
		P plugin = null;
		
		if(CollectionUtils.isNotEmpty(plugins)){
			
			if(pluginCache.containsKey(plugins)){
				plugin = (P)pluginCache.get(plugins);
			}else{
				List<P> list = new ArrayList<>(plugins);
				Collections.sort(list, new Comparator<P>(){
					@Override
					public int compare(P p1, P p2) {
						return p2.getPriority() - p1.getPriority();
					}
				});
				
				plugin = list.get(0);
				pluginCache.putIfAbsent(plugins, plugin);
			}
			
		}else{
			throw new ValidationException("no plugin was found");
		}
		
		return plugin;
	}
	
//	@SuppressWarnings("unchecked")
//	public static<P> P getInstance(String pluginName, String defaultPluginName, Class<? super P> category){
//		PluginManager bean = FrameworkHelper.getBean(PluginManager.class);
//		P p = (P)bean.getPlugin(pluginName, defaultPluginName);
//		return p;
//	}
//
//	public static<P> P getInstance(String pluginName, Class<? super P> category){
//		return getInstance(pluginName, null, category);
//	}
//	
//	private Plugin getPlugin(String pluginName, String defaultPluginName){
//		Plugin target = null;
//		
//		if(CollectionUtils.isNotEmpty(plugins)){
//			Plugin defaultPlugin = null;
//			
//			Set<Plugin> candidates = new TreeSet<>(new Comparator<Plugin>(){
//				@Override
//				public int compare(Plugin p1, Plugin p2) {
//					return p2.getPriority() - p1.getPriority();
//				}
//			});
//			
//			for(Plugin p : plugins){
//				if(p.getPluginName().equals(pluginName)){
//					candidates.add(p);
//				}
//				if(p.getPluginName().equals(StringUtils.trimToEmpty(defaultPluginName))){
//					defaultPlugin = p;
//				}
//			}
//			
//			if(candidates.size() > 0){
//				target = candidates.iterator().next();
//			}else{
//				target = defaultPlugin;
//			}
//		}
//		
//		return target;
//	}
	
//	private Plugin getPlugin(String pluginName, Class<?> category){
//		Plugin target = null;
//		
//		if(CollectionUtils.isNotEmpty(plugins)){
//			Plugin defaultPlugin = null;
//			
//			Set<Plugin> candidates = new TreeSet<>(new Comparator<Plugin>(){
//				@Override
//				public int compare(Plugin p1, Plugin p2) {
//					return p2.getPriority() - p1.getPriority();
//				}
//			});
//			
//			for(Plugin p : plugins){
//				@SuppressWarnings("unchecked")
//				Set<Class<?>> supers = ReflectionUtils.getAllSuperTypes(p.getClass());
//				
//				if(supers.contains(category)){
//					if(p.getPluginName().equals(pluginName)){
//						target = p;
//						candidates.add(p);
//					}else if(PluginAdaptor.DEFAULT_PLUGIN_NAME.equals(StringUtils.trimToEmpty(p.getPluginName()))){
//						defaultPlugin = p;
//					}
//				}
//			}
//			
//			if(candidates.size() > 0){
//				target = candidates.iterator().next();
//			}else {
//				target = defaultPlugin;
//			}
//		}
//		
//		return target;
//	}

}
